/************************************************************************************
* Description:128*64???OLED???????,?????????(heltec.taobao.com)?SD1306??IIC???????
*
* Others: none;
*
* Function List:
*	1. void I2C_Configuration(void) -- ??CPU???I2C
* 2. void I2C_WriteByte(uint8_t addr,uint8_t data) -- ?????????byte???
* 3. void WriteCmd(unsigned char I2C_Command) -- ???
* 4. void WriteDat(unsigned char I2C_Data) -- ???
* 5. void OLED_Init(void) -- OLED????
* 6. void OLED_SetPos(unsigned char x, unsigned char y) -- ???????
* 7. void OLED_Fill(unsigned char fill_Data) -- ????
* 8. void OLED_CLS(void) -- ??
* 9. void OLED_ON(void) -- ??
* 10. void OLED_OFF(void) -- ??
* 11. void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize) -- ?????(?????6*8?8*16??)
* 12. void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N) -- ????(???????,????codetab.h?)
* 13. void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]) -- BMP??
*
* History: none;
*
*************************************************************************************/
 
#include "oled_i2c.h"
#include "delay.h"
#include "codetab.h"
 
//extern 	 u8 display_1[4];                   //????(oled????????????)
extern u8 display_time_flag;
 
//???IIC
void IIC_Init2(void)
{					     
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	//??GPIOB??
	   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //????
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); 	//PB6,PB7 ???
	
}
//??IIC????
void IIC_Start(void)
{
	SDA_OUT();     //sda???
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	//delay_us(4);
 	IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
	//delay_us(4);
	IIC_SCL=0;//??I2C??,????????? 
}	 
 
//??IIC????
void IIC_Stop(void)
{
	SDA_OUT();//sda???
	IIC_SCL=0;
	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 	//delay_us(4);
	IIC_SCL=1; 
	IIC_SDA=1;//??I2C??????
	//delay_us(4);							   	
}
 
//????????
//???:1,??????
//        0,??????
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	SDA_IN();      //SDA?????  
	IIC_SDA=1;/*delay_us(1)*/;	   
	IIC_SCL=1;/*delay_us(1)*/;	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL=0;//????0 	   
	return 0;  
} 
 
//??ACK??
void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	//delay_us(2);
	IIC_SCL=1;
	//delay_us(2);
	IIC_SCL=0;
}
 
//???ACK??		    
void IIC_NAck(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	//delay_us(2);
	IIC_SCL=1;
	//delay_us(2);
	IIC_SCL=0;
}	
 
//IIC??????
//????????
//1,???
//0,???			  
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	  SDA_OUT(); 	    
    IIC_SCL=0;//??????????
    for(t=0;t<8;t++)
    {              
        //IIC_SDA=(txd&0x80)>>7;
		if((txd&0x80)>>7)
			IIC_SDA=1;
		else
			IIC_SDA=0;
		txd<<=1; 	  
		//delay_us(2);   //?TEA5767??????????
		IIC_SCL=1;
		//delay_us(2); 
		IIC_SCL=0;	
		//delay_us(2);
    }	 
} 
 
//?1???,ack=1?,??ACK,ack=0,??nACK   
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();//SDA?????
    for(i=0;i<8;i++ )
	{
        //IIC_SCL=0; 
        delay_us(2);
		//IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
		//delay_us(1); 
    }					 
    if (!ack)
        IIC_NAck();//??nACK
    else
        IIC_Ack(); //??ACK   
    return receive;
}
 
//?AT24CXX??????????
//WriteAddr  :?????????    
//DataToWrite:??????
void WriteCmd(unsigned char I2C_Command)
{				   	  	    																 
    IIC_Start();  
	IIC_Send_Byte(0X78);   //
	IIC_Wait_Ack();	 										  		   
	IIC_Send_Byte(0X00);    	 //????							   
	IIC_Wait_Ack();  		  
	IIC_Send_Byte(I2C_Command);    	 //????							   
	IIC_Wait_Ack();
    IIC_Stop();//????????  
}
 
void WriteDat(unsigned char I2C_Data)//???
{
	//I2C_WriteByte(0x40, I2C_Data);
	IIC_Start();  
	IIC_Send_Byte(OLED_ADDRESS);   //
	IIC_Wait_Ack();	 										  		   
	IIC_Send_Byte(0x40);    	 //????							   
	IIC_Wait_Ack();  		  
	IIC_Send_Byte(I2C_Data);    	 //????							   
	IIC_Wait_Ack();
    IIC_Stop();//???????? 
	 
}
//void WriteCmd(unsigned char I2C_Command)//???
//{
//	I2C_WriteByte(0x00, I2C_Command);
//}
 
//void WriteDat(unsigned char I2C_Data)//???
//{
//	I2C_WriteByte(0x40, I2C_Data);
//}
 
void OLED_Init(void)
{
	IIC_Init2();
	//I2C_Configuration();		//IIC????
	delay_ms(100); //????????
	
	WriteCmd(0xAE); //display off
	WriteCmd(0x20);	//Set Memory Addressing Mode	
	WriteCmd(0x10);	//00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
	WriteCmd(0xb0);	//Set Page Start Address for Page Addressing Mode,0-7
	WriteCmd(0xc8);	//Set COM Output Scan Direction
	WriteCmd(0x00); //---set low column address
	WriteCmd(0x10); //---set high column address
	WriteCmd(0x40); //--set start line address
	WriteCmd(0x81); //--set contrast control register
	WriteCmd(0xff); //???? 0x00~0xff
	WriteCmd(0xa1); //--set segment re-map 0 to 127
	WriteCmd(0xa6); //--set normal display
	WriteCmd(0xa8); //--set multiplex ratio(1 to 64)
	WriteCmd(0x3F); //
	WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
	WriteCmd(0xd3); //-set display offset
	WriteCmd(0x00); //-not offset
	WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency
	WriteCmd(0xf0); //--set divide ratio
	WriteCmd(0xd9); //--set pre-charge period
	WriteCmd(0x22); //
	WriteCmd(0xda); //--set com pins hardware configuration
	WriteCmd(0x12);
	WriteCmd(0xdb); //--set vcomh
	WriteCmd(0x20); //0x20,0.77xVcc
	WriteCmd(0x8d); //--set DC-DC enable
	WriteCmd(0x14); //
	WriteCmd(0xaf); //--turn on oled panel
}
 
void OLED_SetPos(unsigned char x, unsigned char y) //???????
{ 
	WriteCmd(0xb0+y);
	WriteCmd(((x&0xf0)>>4)|0x10);
	WriteCmd((x&0x0f)|0x01);
}
 
void OLED_Fill(unsigned char fill_Data)//????
{
	unsigned char m,n;
	for(m=0;m<8;m++)
	{
		WriteCmd(0xb0+m);		//page0-page1
		WriteCmd(0x00);		//low column start address
		WriteCmd(0x10);		//high column start address
		for(n=0;n<128;n++)
			{
				WriteDat(fill_Data);
			}
	}
}
 
void OLED_CLS(void)//??
{
	OLED_Fill(0x00);
}
 
//--------------------------------------------------------------
// Prototype      : void OLED_ON(void)
// Calls          : 
// Parameters     : none
// Description    : ?OLED??????
//--------------------------------------------------------------
void OLED_ON(void)
{
	WriteCmd(0X8D);  //?????
	WriteCmd(0X14);  //?????
	WriteCmd(0XAF);  //OLED??
}
 
//--------------------------------------------------------------
// Prototype      : void OLED_OFF(void)
// Calls          : 
// Parameters     : none
// Description    : ?OLED?? -- ?????,OLED????10uA
//--------------------------------------------------------------
void OLED_OFF(void)
{
	WriteCmd(0X8D);  //?????
	WriteCmd(0X10);  //?????
	WriteCmd(0XAE);  //OLED??
}
 
//--------------------------------------------------------------
// Prototype      : void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
// Calls          : 
// Parameters     : x,y -- ?????(x:0~127, y:0~7); ch[] -- ???????; TextSize -- ????(1:6*8 ; 2:8*16)
// Description    : ??codetab.h??ASCII??,?6*8?8*16???
//--------------------------------------------------------------
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{
	unsigned char c = 0,i = 0,j = 0;
	switch(TextSize)  
	{
		case 1:
		{
			while(ch[j] != '\0')
			{
				c = ch[j] - 32;
				if(x > 126)         //??????
				{
					x = 0;
					y++;
				}
				OLED_SetPos(x,y);
				for(i=0;i<6;i++)
					WriteDat(F6x8[c][i]);  //???????
				x += 6;           //??????,??+6???
				j++;  //?????
			}
		}break;
		case 2:
		{
			while(ch[j] != '\0')
			{
				c = ch[j] - 32;
				if(x > 120)
				{
					x = 0;
					y++;
				}
				OLED_SetPos(x,y);
				for(i=0;i<8;i++)
					WriteDat(F8X16[c*16+i]);  //????,c*16??????
				OLED_SetPos(x,y+1);//????(????,?8?)
				for(i=0;i<8;i++)
					WriteDat(F8X16[c*16+i+8]);
				x += 8;
				j++;
			}
		}break;
	}
}
 
//--------------------------------------------------------------
// Prototype      : void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
// Calls          : 
// Parameters     : x,y -- ?????(x:0~127, y:0~7); N:???codetab.h????
// Description    : ??codetab.h????,16*16??
//--------------------------------------------------------------
void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
{
	unsigned char wm=0;
	unsigned int  adder=32*N;
	OLED_SetPos(x , y);
	for(wm = 0;wm < 16;wm++)
	{
		WriteDat(F16x16[adder]);
		adder += 1;
	}
	OLED_SetPos(x,y + 1);
	for(wm = 0;wm < 16;wm++)
	{
		WriteDat(F16x16[adder]);
		adder += 1;
	}
}
 
//--------------------------------------------------------------
// Prototype      : void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]);
// Calls          : 
// Parameters     : x0,y0 -- ?????(x0:0~127, y0:0~7); x1,y1 -- ?????(???)???(x1:1~128,y1:1~8)
// Description    : ??BMP??
//--------------------------------------------------------------
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
{
	unsigned int j=0;
	unsigned char x,y;
 
  if(y1%8==0)
		y = y1/8;
  else
		y = y1/8 + 1;
	for(y=y0;y<y1;y++)
	{
		OLED_SetPos(x0,y);
    for(x=x0;x<x1;x++)
		{
			WriteDat(BMP[j++]);
		}
	}
}
 